﻿// Copyright (c) 2012-2013 fancidev
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Util.Forms
{
    [DefaultEvent("ActiveFolderChanged")]
    public partial class VirtualFolderTreeView : UserControl
    {
        private List<IVirtualFolder> rootFolders = new List<IVirtualFolder>();
        private IVirtualFolder activeFolder = null;
        private Dictionary<IVirtualFolder, TreeNode> nodeMap = new Dictionary<IVirtualFolder, TreeNode>();

        public VirtualFolderTreeView()
        {
            InitializeComponent();
        }

        public void Clear()
        {
            rootFolders.Clear();
            nodeMap.Clear();
            activeFolder = null;
            tvFolders.Nodes.Clear();
        }

        /// <summary>
        /// Adds a root folder to be displayed in the tree view.
        /// </summary>
        public void AddRootFolder(IVirtualFolder folder)
        {
            rootFolders.Add(folder);
            tvFolders.Nodes.Add(CreateTreeNodeFromFolder(folder));
        }

        private TreeNode CreateTreeNodeFromFolder(IVirtualFolder vFolder)
        {
            IVirtualItem vItem = vFolder as IVirtualItem;
            TreeNode node = new TreeNode();
            node.Text = (vItem != null) ? vItem.DisplayName : "";
            node.ImageIndex = -1;
            node.SelectedImageIndex = -1;
            node.Tag = vFolder;

            // Add the folder's icon to the image list.
            IExtractIcon vIcon = vFolder as IExtractIcon;
            if (vIcon != null)
            {
                node.ImageIndex = vIcon.ExtractIconToImageList(
                    ExtractIconType.SmallIcon, imageList1);
                node.SelectedImageIndex = node.ImageIndex;
            }

            // Subscribe to the FolderChanged event if available.
            INotifyFolderChanged vNotify = vFolder as INotifyFolderChanged;
            if (vNotify != null)
            {
                vNotify.FolderChanged += OnFolderChanged;
            }

            // Add the vFolder => node mapping to the node map.
            nodeMap[vFolder] = node;

            return node;
        }

        private void OnFolderChanged(object sender, FolderChangedEventArgs e)
        {
            IVirtualFolder vFolder = sender as IVirtualFolder;
            
            // Find the tree node corresponding to the changed folder.
            // string key = (vFolder as IVirtualItem).FullName;
            TreeNode node;
            if (!nodeMap.TryGetValue(vFolder, out node))
                return;

            if (e.ChangeType == FolderChangeType.ItemsAdded)
            {
                if (e.Item is IVirtualFolder)
                {
                    node.Nodes.Add(CreateTreeNodeFromFolder(e.Item as IVirtualFolder));
                }
            }
        }

        /// <summary>
        /// Gets the folder currently being selected.
        /// </summary>
        [Browsable(false)]
        public IVirtualFolder ActiveFolder
        {
            get { return activeFolder; }
        }

        /// <summary>
        /// Occurs when the ActiveFolder property has changed.
        /// </summary>
        public event EventHandler ActiveFolderChanged;

        private void tvFolders_AfterSelect(object sender, TreeViewEventArgs e)
        {
            this.activeFolder = e.Node.Tag as IVirtualFolder;
            if (ActiveFolderChanged != null)
                ActiveFolderChanged(this, null);
        }

        private void VirtualFolderTreeView_Load(object sender, EventArgs e)
        {
            tvFolders.SetWindowTheme("explorer");
        }
    }
}
